package com.vcredit.creditcat.service;

import java.util.Random;
import java.util.UUID;

import com.vcredit.creditcat.model.CustAccount;
import com.vcredit.creditcat.model.LoginLog;
import com.vcredit.creditcat.redis.RedisServiceExt;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.vcredit.creditcat.exception.AppTokenException;

@Service
public class AppTokenService {

	public final static String REDIS_APP_TOKEN = "token:APPTOKEN_";
	public final static Long REDIS_APP_TOKEN_EXPIRED = 7200L;
	public final static String APP_TOKEN_SEPERATOR = "_";
	@Autowired
	private RedisServiceExt redisExtService;
	@Autowired
	private LoginLogService loginLogService;

	public String generateToken(Long accountId, Long custId) {
		return UUID.randomUUID().toString().replaceAll("-", "") + APP_TOKEN_SEPERATOR + accountId + APP_TOKEN_SEPERATOR + custId;
	}

	public String generateTokenKey(Long custId) {
		return REDIS_APP_TOKEN + custId;
	}

	public void updateAppToken(String token, Long custId) throws AppTokenException {
		if (StringUtils.isBlank(token) || null == custId) {
			throw new AppTokenException("参数不能为null");
		}
		String tokenKey = generateTokenKey(custId);
		if (null == redisExtService.get(tokenKey)) {
			redisExtService.put(tokenKey, token, REDIS_APP_TOKEN_EXPIRED);
		} else {
			redisExtService.del(tokenKey);
			redisExtService.put(tokenKey, token, REDIS_APP_TOKEN_EXPIRED);
		}
	}

	public void checkAppToken(String token) throws AppTokenException {
		if (StringUtils.isBlank(token)) {
			throw new AppTokenException("token不能为null");
		}
		Long custId = getCustIdFromToken(token);
		Long accountId = getAccountIdFromToken(token);
		checkAppToken(token, custId, accountId);
	}

	public String checkAppToken(String token, Long custId, Long accountId) throws AppTokenException {
		synchronized (token.intern()) {
			if (null == custId) {
				throw new AppTokenException("参数不能为null");
			}
			String tokenKey = generateTokenKey(custId);
			if (null == redisExtService.get(tokenKey) || !redisExtService.get(tokenKey).equals(token)) {
				LoginLog loginLog = loginLogService.findByAccountId(accountId);
				if (loginLog != null && loginLog.getLoginToken().equals(token.replace(":", ""))) {
					return loginLog.getDeviceNo();
				} else {
					throw new AppTokenException("token已经失效");
				}
			} else {
				redisExtService.del(tokenKey);
			}
			redisExtService.put(tokenKey, token, REDIS_APP_TOKEN_EXPIRED);
			return null;
		}
	}

	public String getLoginNameFromToken(String token) throws AppTokenException {
		if (StringUtils.isBlank(token)) {
			throw new AppTokenException("token不能为null");
		}
		return token.split(APP_TOKEN_SEPERATOR)[1];

	}

	public Long getAccountIdFromToken(String token) throws AppTokenException {
		if (StringUtils.isBlank(token)) {
			throw new AppTokenException("token不能为null");
		}
		return Long.parseLong(token.split(APP_TOKEN_SEPERATOR)[1]);

	}

	public Long getCustIdFromToken(String token) throws AppTokenException {
		if (StringUtils.isBlank(token)) {
			throw new AppTokenException("token不能为null");
		}
		return Long.parseLong(token.split(APP_TOKEN_SEPERATOR)[2]);
	}

	public void delete(String token) throws AppTokenException {
		Long custId = getCustIdFromToken(token);
		delete(custId);
	}

	public void delete(Long custId) throws AppTokenException {
		String tokenKey = generateTokenKey(custId);
		redisExtService.del(tokenKey);

	}

	/**
	 * 校验token是否有效
	 * 
	 * @param custAccount
	 * @return
	 * @throws Exception
	 */
	public boolean tokenIsVaild(CustAccount custAccount, String appToken) throws Exception {
		if (null == custAccount || StringUtils.isBlank("appToken")) {
			return false;
		}
		Long custId = getCustIdFromToken(appToken);
		Long accountId = getAccountIdFromToken(appToken);

		synchronized (appToken.intern()) {
			if (null == custId) {
				return false;
			}
			String tokenKey = generateTokenKey(custId);
			// 1、判断token是否在token缓存中失效
			if (null == redisExtService.get(tokenKey) || !redisExtService.get(tokenKey).equals(appToken)) {
				return false;
			} else {
				// 2、当前token未失效并且当前token最后一次登录记录和当前登录用户能够吻合
				LoginLog loginLog = loginLogService.findByAccountId(accountId);
				if (loginLog != null && !loginLog.getLoginToken().equals(appToken.replace(":", ""))) {
					return false;
				}
				redisExtService.del(tokenKey);
			}
			// 3、如果以上条件都符合则更新此token的过期时间
			redisExtService.put(tokenKey, appToken, REDIS_APP_TOKEN_EXPIRED);
			return true;
		}
	}

	static final int MAX = 100000;
	static final String[] arr = new String[MAX];

	/*public static void main(String[] args) {
		String str2 = "SEUCalvin";// 新加的一行代码，其余不变
		String str1 = new String("SEU") + new String("Calvin");
		System.out.println(str1.intern() == str1);
		System.out.println(str1 == "SEUCalvin");

		// 为长度为10的Integer数组随机赋值
		Integer[] sample = new Integer[10];
		Random random = new Random(1000);
		for (int i = 0; i < sample.length; i++) {
			sample[i] = random.nextInt();
		}
		// 记录程序开始时间
		long t = System.currentTimeMillis();
		// 使用/不使用intern方法为10万个String赋值，值来自于Integer数组的10个数
		for (int i = 0; i < MAX; i++) {
			 arr[i] = new String(String.valueOf(sample[i % sample.length]));
			 //arr[i] = new String(String.valueOf(sample[i % sample.length])).intern();
		}
		System.out.println((System.currentTimeMillis() - t) + "ms");
		System.gc();
	}*/
}
